#include <seminix/list.h>
#include <seminix/param.h>
#include <seminix/cpu.h>
#include <seminix/smp.h>
#include <seminix/mm.h>
#include <seminix/sched.h>
#include <seminix/init.h>
#include <seminix/spinlock.h>
#include <seminix/slab.h>

// DEFINE_SPINLOCK(tcb_list_lock);
// LIST_HEAD(tcb_list);

// static DEFINE_SPINLOCK(tid_lock);
// static struct idtable *tid_bits;

// static struct kmem_cache *tcb_cachep;
// static struct kmem_cache *tcb_stack_cachep;

// static void tcb_list_insert(struct task_struct *tsk)
// {
//     spin_lock(&tcb_list_lock);
//    // list_add(&tsk->tcb_node, &tcb_list);
//     spin_unlock(&tcb_list_lock);
// }

// static void tcb_list_remove(struct task_struct *tsk)
// {
//     spin_lock(&tcb_list_lock);
//    // list_del(&tsk->tcb_node);
//     spin_unlock(&tcb_list_lock);
// }

// static int alloc_tid_idtable(void)
// {
//     return 0;
//     // int id;

//     // spin_lock(&tid_lock);
//     // id = id_table_get_free(tid_bits, 0);
//     // if (id < 0)
//     //     return -ENOMEM;
//     // spin_unlock(&tid_lock);
//     // return id;
// }

// static void free_tid_idtable(int tid)
// {
//     spin_lock(&tid_lock);
//     //id_table_put(tid_bits, tid);
//     spin_unlock(&tid_lock);
// }

// static inline struct task_struct *alloc_tcb_struct(void)
// {
//     return kmem_cache_alloc(tcb_cachep, GFP_KERNEL | GFP_ZERO);
// }

// static inline void free_tcb_struct(struct task_struct *tsk)
// {
//     kmem_cache_free(tcb_cachep, tsk);
// }

// static inline void *alloc_tcb_stack(void)
// {
//     return kmem_cache_alloc(tcb_stack_cachep, GFP_KERNEL);
// }

// static inline void free_tcb_stack(void *stack)
// {
//     kmem_cache_free(tcb_stack_cachep, stack);
// }

// static void tcb_struct_init(struct task_struct *tsk)
// {
//     atomic_set(&tsk->usage, 1);
//     raw_spin_lock_init(&tsk->pi_lock);

//     set_task_stack_end_magic(tsk);
//     atomic_set(&tsk->stack_refcount, 1);

//     //spin_lock_init(&tsk->sighand.siglock);

//     tsk->restart_block.fn = do_no_restart_syscall;

//     //init_user_thread(&tsk->thread);
// }

// struct task_struct *tcb_struct_create(void)
// {
//     struct task_struct *tsk;

//     tsk = alloc_tcb_struct();
//     if (!tsk)
//         goto out;

//     tsk->stack = alloc_tcb_stack();
//     if (!tsk->stack)
//         goto free_tsk;

//     tsk->tgid = alloc_tid_idtable();
//     if (tsk->tgid < 0)
//         goto free_tsk_tcb;

//  //   if (cnode_init(tsk))
//  //       goto free_tid;
//   //  rlimit_init(&tsk->crlimit);

//     //init_user_thread_info(&tsk->thread_info);
//     tcb_struct_init(tsk);
//     tcb_list_insert(tsk);

//     return tsk;

// //free_tid:
//     free_tid_idtable(tsk->tgid);
// free_tsk_tcb:
//     free_tcb_stack(tsk->stack);
// free_tsk:
//     free_tcb_struct(tsk);
// out:
//     return NULL;
// }

// void __put_task_struct(struct task_struct *tsk)
// {
//     WARN_ON(atomic_read(&tsk->usage));
//     WARN_ON(tsk == current);
//     WARN_ON(tsk->mm);

//     tcb_list_remove(tsk);
//     free_tid_idtable(tsk->tgid);
//     //cnode_free(tsk);
//     //rlimit_free(tsk);
//     put_task_stack(tsk);
//     free_tcb_struct(tsk);
// }

// void put_task_stack(struct task_struct *tsk)
// {
//     if (atomic_dec_and_test(&tsk->stack_refcount))
//         free_tcb_stack(tsk->stack);
// }

// /*
//  *  'fork.c' contains the help-routines for the 'fork' system call
//  * (see also entry.S and others).
//  * Fork is rather simple, once you get the hang of it, but the memory
//  * management can be a bitch. See 'mm/memory.c': 'copy_page_range()'
//  */

// void set_task_stack_end_magic(struct task_struct *tsk)
// {
//     unsigned long *stackend;

//     stackend = end_of_stack(tsk);
//     *stackend = STACK_END_MAGIC;	/* for overflow detection */
// }

struct task_struct *__init idle_task_init_once(int cpu)
{
    return NULL;
}
//     struct task_struct *idle;

//     if (cpu == boot_cpu_id()) {
//         idle = current;
//         goto out;
//     }

//     idle = kzalloc(sizeof (*idle), GFP_KERNEL);
//     if (!idle)
//         goto out1;
//     idle->stack = kmalloc(THREAD_SIZE, GFP_KERNEL);
//     if (!idle->stack)
//         goto free_idle;
//     idle->tgid = -cpu;
//     //init_idle_thread_info(&idle->thread_info);
//     tcb_struct_init(idle);
// out:
//     mm_set_task(&init_mm, idle);
//     tcb_list_insert(idle);
//     init_idle(idle, cpu);
//     return idle;
// free_idle:
//     kfree(idle);
// out1:
//     return NULL;
// }

// static int __init tcb_and_idtable_init(void)
// {
//     tid_bits = NULL;
//     // tid_bits = id_table_create(NR_TCB_DEFAULT, 0);
//     // if (!tid_bits)
//     //     panic("failed to tid table init!\n");
//     // if (id_table_get_free(tid_bits, 0))
//     //     panic("tid first id none zero!\n");

//     // tcb_cachep = KMEM_CACHE(task_struct, SLAB_PANIC);
//     // tcb_stack_cachep = kmem_cache_create("tcb_stack", THREAD_SIZE, THREAD_SIZE, SLAB_PANIC, NULL);

//     return 0;
// }
// core_initcall(tcb_and_idtable_init)
